package tp.pr5;

import tp.pr5.items.CodeCard;

/**
 *A street links two places A and B in one direction. If it is defined as Street(A,NORTH,B) it means that Place B is at NORTH of Place A. Streets are two-way streets, i.e. if B is at NORTH of A then A is at SOUTH of B.
 *Some streets are closed and a code (contained in a code card) is needed to open them
 * @author VICTOR & HENAR
 * @see Place
 * @see CodeCard
 */

public class Street {
	private Place source;
	private Direction direction;
	private Place target;
	private boolean isOpen;
	private String code;
	
	/**
	 * Creates an open street and it have not any code to open or close it
	 * @param source - Source place
	 * @param direction - Represents how is placed the target place with respect to the source place.
	 * @param target - Target place
	 */
	public Street(Place source, Direction direction, Place target) 
	{
		this.source		= source;
		this.direction 	= direction;
		this.target 	= target;
		this.isOpen 	= true;
	}
	
	/**
	 * Creates an closed street with code to open or close it
	 * @param source - Source place
	 * @param direction - Represents how is placed the target place with respect to the source place.
	 * @param target - Target place
	 * @param isOpen - Is open
	 * @param code - Code
	 */
	
	public Street(Place source, Direction direction, Place target, boolean isOpen, String code) {
		this.source = source;
		this.direction = direction;
		this.target = target;
		this.isOpen = isOpen;
		this.code = code;
	}


	/**
	 * Checks if the street comes out from a place in a given direction. Remember that streets are two-way
	 * @param place The place to check
	 * @param whichDirection Direction used.
	 * @return Returns true if the street comes out from the input Place.
	 */
	public boolean comeOutFrom (Place place, Direction whichDirection)
	{
		return ((this.source.equals(place) && whichDirection == direction) 
			 || (this.target.equals(place) && whichDirection == direction.opposite()));
	}
	
	/**
	 * Returns the place of the other side from the place whereAmI. This method does not consider whether the street is open or closed.
	 * @param whereAmI  The place where I am.
	 * @return It returns the Place at the other side of the street(even if the street is closed).Returns null if whereAmI does not belong to the street
	 */
	public Place nextPlace (Place whereAmI)
	{
		if (this.source.equals(whereAmI))
			return this.target;
		else if (this.target.equals(whereAmI))
			return this.source;
		else 
			return null;
	}
	
	/**
	 * Checks if the street is open or closed
	 * @return true, if the street is open, and false when the street is closed
	 */
	
	public boolean isOpen()
	{
		return isOpen;
	}
	
	/**
	 * Tries to open a street using a code card. Codes must match in order to complete this action
	 * @param card - A code card to open the street
	 * @return true if the action has been completed
	 */
	public boolean open(CodeCard card)
	{
		if (this.code.equalsIgnoreCase(card.getCode()))
		{
			this.isOpen = true;
			return true;
		}
		else 
			return false;
	}
	
	/**
	 * Tries to close a street using a code card. Codes must match in order to complete this action
	 * @param card - A code card to close the street
	 * @return true if the action has been completed
	 */
	public boolean close(CodeCard card)
	{
		if (this.code.equalsIgnoreCase(card.getCode()))
		{
			isOpen = false;
			return true;
		}
		else return false;
	}
}
